package test
{
	import control.macro.HumanWorldController;
	import control.micro.AttackingAIBattleController;
	import control.micro.AttackingHumanBattleController;
	import control.micro.BattleController;
	import control.micro.DefendingAIBattleController;
	import control.micro.DefendingHumanBattleController;
	import events.BattleEvent;
	import events.WorldEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import model.BattleReport;
	import model.macro.Armor;
	import model.macro.Building;
	import model.macro.Player;
	import model.macro.RangedWeapon;
	import model.macro.Territory;
	import model.macro.Unit;
	import model.macro.Weapon;
	import model.macro.World;
	import model.micro.Battle;
	import view.FrameRateCounter;
	import view.macro.MapSprite;
	import view.macrogui.MacroHUD;
	import view.micro.BattleSprite;
	import view.microgui.HUDSprite;
	
	/**
	 * Test of the whole game. Shitty code is allowed here.
	 */
	public class MacroTest extends Sprite
	{
		private var human_world_controller:HumanWorldController;
		private var counter:FrameRateCounter;
		private var world:World;
		private var map:MapSprite;
		private var hud:MacroHUD;
		private var previous_battles:Vector.<BattleReport>;
		
		public function MacroTest()
		{
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			previous_battles = new Vector.<BattleReport>;
			
			// players
			var players:Vector.<Player> = new Vector.<Player>();
			players.push(new Player("Player 1", 0x0000FF));
			players.push(new Player("Player 2", 0xFF0000));
			_current_player = players[0];
			players[0].hostilePlayers.push(players[1]);
			players[1].hostilePlayers.push(players[0]);
			
			var territories:Vector.<Territory> = new Vector.<Territory>();
			
			// TODO: load territories
			for (var i:int = 0; i < 12; i++)
			{
				territories.push(new Territory("Territory " + i));
			}
			
			territories[0].owner = players[0];
			territories[1].owner = players[1];
			
			world = new World(territories, players, "Test", players[0]);
			
			world.addEventListener(WorldEvent.BATTLE_BEGIN, startMicroGame);
			
			// mark adjacent territories
			var adjacent:Vector.<Point> = new Vector.<Point>();
			adjacent.push(new Point(4, 9));
			adjacent.push(new Point(2, 6));
			adjacent.push(new Point(0, 1));
			adjacent.push(new Point(0, 4));
			adjacent.push(new Point(0, 5));
			adjacent.push(new Point(5, 6));
			adjacent.push(new Point(6, 7));
			adjacent.push(new Point(7, 11));
			for each (var pair:Point in adjacent)
			{
				world.territories[pair.x].adjacent_territories.push(world.territories[pair.y]);
				world.territories[pair.y].adjacent_territories.push(world.territories[pair.x]);
			}
			
			world.territories[0].buildings.push(Building.BARRACKS);
			for each (var territory:Territory in world.territories)
			{
				territory.addBuilding(Building.BLACKSMITH);
				territory.addBuilding(Building.MARKET);
				territory.addBuilding(Building.SEIGE_WORKSHOP);
			}
			world.territories[0].units.push(new Unit(world.players[0], Weapon.SWORD, Armor.CHAINMAIL));
			world.territories[0].units.push(new Unit(world.players[0], Weapon.SWORD, Armor.CLOTH));
			world.territories[0].units.push(new Unit(world.players[0], Weapon.HALBERD, Armor.FULLPLATE));
			
			world.territories[1].units.push(new Unit(world.players[1], Weapon.HALBERD, Armor.CHAINMAIL));
			world.territories[1].units.push(new Unit(world.players[1], RangedWeapon.LONGBOW, Armor.CHAINMAIL));
			world.territories[1].units.push(new Unit(world.players[1], RangedWeapon.LONGBOW, Armor.CHAINMAIL));
			world.territories[1].units.push(new Unit(world.players[1], RangedWeapon.LONGBOW, Armor.CHAINMAIL));
			world.territories[1].units.push(new Unit(world.players[1], RangedWeapon.LONGBOW, Armor.CHAINMAIL));
			
			map = new MapSprite(world.territories, world);
			addChild(map);
			
			hud = new MacroHUD(world, map);
			addChild(hud);
			
			counter = new FrameRateCounter();
			counter.x = 5;
			counter.y = stage.stageHeight - counter.height;
			addChild(counter);
			
			human_world_controller = new HumanWorldController(world.players[0], world, stage);
		}
		
		// model should auto update
		protected function startMicroGame(e:WorldEvent):void
		{
			toggleMacro();
			var battle:Battle = new Battle((e.data['attackingUnits'] as Vector.<Unit>).concat(), e.data['defendingTerritory'].units, e.data['defendingTerritory'].fortress, e.data['defendingTerritory'], e.data['attackingTerritory']);
			
			// views
			var battle_sprite:BattleSprite = new BattleSprite(battle);
			addChild(battle_sprite);
			
			var microHUD:HUDSprite = new HUDSprite(battle);
			addChild(microHUD);
			
			battle_sprite.y = stage.stageHeight;
			
			// controllers
			
			var defending_controller:BattleController;
			var attacking_controller:BattleController;
			
			if (human_world_controller.player == battle.invading_territoy.owner) // Defending human
			{
				defending_controller = new DefendingAIBattleController(battle);
				attacking_controller = new AttackingHumanBattleController(battle, stage);
			}
			else if (human_world_controller.player == battle.defending_territory.owner) // Attacking human
			{
				defending_controller = new DefendingHumanBattleController(battle, stage);
				attacking_controller = new AttackingAIBattleController(battle);
			}
			else if (1 == 2) // Both human (Okay, this shouldn't exist)
			{
				defending_controller = new DefendingHumanBattleController(battle, stage);
				attacking_controller = new AttackingHumanBattleController(battle, stage);
			}
			else // Both AI (simulation)
			{
				defending_controller = new DefendingAIBattleController(battle);
				attacking_controller = new AttackingAIBattleController(battle);
			}
			
			addEventListener(Event.ENTER_FRAME, update);
			battle.addEventListener(BattleEvent.BATTLE_ENDED, battleEnded);
			
			/**
			 * Called every frame.
			 * @param	e	EnterFrame event
			 */
			function update(e:Event):void
			{
				if (battle != null)
				{
					battle.update();
					battle_sprite.update();
					hud.update();
					defending_controller.update();
					attacking_controller.update();
				}
				else
				{
					toggleMacro();
					removeEventListener(Event.ENTER_FRAME, update);
					removeChild(battle_sprite);
					removeChild(microHUD);
				}
			}
			
			function battleEnded(e:BattleEvent):void
			{
				previous_battles.push(e.data as BattleReport);
				processLastBattle();
				battle = null;
			}
		}
		
		public function processLastBattle():void
		{
			var report:BattleReport = previous_battles[previous_battles.length - 1];
			
			if (report.win_condition == BattleReport.RETREAT_BY_ATTACKER)
			{
				// Do something...
			}
			else if (report.win_condition == BattleReport.RETREAT_BY_DEFENDER)
			{
				world.territories[world.territories.indexOf(report.battle_territory)].owner = report.winner;
				world.transferUnits(report.invading_territory, report.remainingUnits, report.battle_territory);
			}
		}
		
		protected function toggleMacro():void
		{
			map.visible = !map.visible;
			hud.visible = !hud.visible;
		}
	}

}